import { Sprite, CanvasSource, Texture } from "pixi.js";
import { TexturePool } from "@/utils/TexturePool.js";
import { ColorExtraction } from "@/utils/ColorExtraction.js";
import { ImageManager } from "@/managers/ImageManager.js";

export class Sprite_PlaneText extends Sprite {
    static fastSpeed=1;
    static slowSpeed=0.5;
    static speed=0;
    constructor(width, height) {
        let canvasSource = new CanvasSource({ width, height });
        let texture = TexturePool.newTexture(canvasSource);
        super(texture);
        this.canvasSource = canvasSource;
        this._context = this.canvasSource.context2D;

        this._context.font = '28px GameFont';
        this._fontSize = 28;
        this._fontItalic = false;
        this.textColor = '#ffffff';
        this.outlineColor = '#000000';
        this.outlineWidth = 4;

        /**
         * @member {{
         *   type:string,
         *   params:any
         * }[]}
         */
        this.data = null;

        this.acculumator=0;

        this.redraw=false;
    }

    destroy(opts) {
        if(this.destroyed)return;
        opts = opts || { children: true };
        if (opts.texture) {
            opts.texture = false;
        }
        if(opts.baseTexture){
            opts.baseTexture=false;
        }
        let texture = this.texture;
        this.texture = Texture.EMPTY;
        this.texture.off('update', this.onViewUpdate, this);

        this.canvasSource.destroy();

        TexturePool.releaseTexture(texture);
        super.destroy(opts);
    }

    get width(){
        return this.canvasSource.width;
    }
    get height(){
        return this.canvasSource.height;
    }

    update(){
        if(this.visible){
            if(this.redraw){
                this.canvasSource.update();
            }
            if(this.data.length){
                this.acculumator+=Sprite_PlaneText.speed;
                if(this.acculumator>18){
                    this.acculumator=0;
                    this.PrintLine();
                }
            }
            
            this.y-=Sprite_PlaneText.speed;
            if(this.y<-this.canvasSource.height){ 
                this.visible=false;
            }
        }
    }
    /**
     * {
     *  width:
     *  height:
     *  data:[]
     * }
     * @param {{
     *   width:number,
     *   height:number,
     *   data:[]
     *  }} textData 
     */
    start(page) {
        this.data = page.data;
        this.canvasSource.resize(page.width, page.height);
        this._context=this.canvasSource.context2D;
        this._context.font = '28px GameFont';
        this.texture.noFrame=true;
        this.texture.update();
        this.texture.noFrame=false;
        this.PrintLine();
    }

    PrintNode(node) {
        if(!node)return;
        switch (node.type) {
            case 'T':
                this.drawText(...node.params); break;
            case 'C':
                this.textColor = ColorExtraction.textColor(...node.params); break;
            case 'I':
                this.drawIcon(...node.params); break;
            case '{':
                this.makeFontBigger(); break;
            case '}':
                this.makeFontSmaller(); break;
        }
    }

    PrintLine() {
        if(this.data&&this.data.length){
            let node = this.data.shift();
            while (node && node.type != '\n') {
                this.PrintNode(node);
                node = this.data.shift();
            }
            
        }
    }

    PrintAll() {
        if(this.data&&this.data.length){
            let node=this.data.shift();
            while(node){
                this.PrintNode(node);
                node=this.data.shift();
            }
        }
    }

    drawText(text, x, y, maxWidth, lineHeight, align) {
        if (text) {
            let tx = x;
            let ty = y + 0.5 * lineHeight + this._fontSize * 0.35;
            let context = this._context;
            context.save();
            maxWidth = maxWidth ?? this._context.measureText(text).width;
            context.textAlign = align ?? 'left';
            this._drawTextOutline(text, tx, ty, maxWidth);
            this._drawTextBody(text, tx, ty, maxWidth);
            context.restore();

            this.redraw = true;
        }
    }

    _drawTextOutline(text, tx, ty, maxWidth) {
        let context = this._context;
        context.strokeStyle = this.outlineColor;
        context.lineWidth = this.outlineWidth;
        context.lineJoin = 'round';
        context.strokeText(text, tx, ty, maxWidth);
    }

    _drawTextBody(text, tx, ty, maxWidth) {
        let context = this._context;
        context.fillStyle = this.textColor;
        context.fillText(text, tx, ty, maxWidth);
    }

    drawIcon(index, iconSize, x, y) {
        ImageManager.loadSystem('IconSet').then(source => {
            let xi = index % 16;
            let yi = (index - xi) / 16;
            let size = iconSize;
            this._context.drawImage(
                source.resource,
                xi * size,
                yi * size,
                size, size,
                x, y, size, size
            );
            ImageManager.releaseSystem('IconSet');
            this.redraw = true;
        });
    }

    makeFontBigger() {
        if (this._fontSize <= 96) {
            this._fontSize += 12;
            this._context.font = `${this._fontSize}px GameFont`;
        }
    }

    makeFontSmaller() {
        if (this._fontSize >= 24) {
            this._fontSize -= 12;
            this._context.font = `${this._fontSize}px GameFont`;
        }
    }
}